/***************************************************************************
 *   Copyright (C) 2007 by vasaka,,,   *
 *   vasaka@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "cleanclass.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
//#include "clusterpoint.h"

CleanClass::CleanClass()
{}
//LoadImage() gets pointer to external image array and its dimension
//and translates it to inner cluster format
void CleanClass::LoadImage ( int* img_,int width_,int height_)
{
  printf("Loading B&W image %dx%d\n",width_,height_);

  ImageInClusterFormat_m.Resize ( img_, width_, height_ );
  ImageInClusterFormat_m.SetAdjacentThrehold_m(20);
  clList_m.resize(0);
  img_m = img_;
  imgout_m = 0;
  Width_m = width_;
  Height_m = height_;
  
  printf("image resized img addr %p\n",img_m);
  for ( int x = 0; x < width_; x++ )
    for ( int y = 0; y < height_; y++ )
    {
      ImageInClusterFormat_m.ClearMarks ( x, y );  
    }
  printf("image filled\n");
}
//---------------------------------------------------------------------------
void CleanClass::CleanPaintBackSimpleBW(int* img_)
{
  printf("CleanPaintBackSimpleBW start\n");
  for ( int x = 0; x < Width_m; x++ )
	for ( int y = 0; y < Height_m; y ++ )
	{
	  img_ [x+Width_m*y] = 255;//ImageInClusterFormat_m.GetColor( x, y )*255; 
  }  
  printf("CleanPaintBackSimpleBW cleanimg, clasters found %d\n",clList_m.size());
  ImageInClusterFormat_m.SetOutput(img_);
  imgout_m = img_;
  
  for ( vector< clInfo >::iterator CP = clList_m.begin();CP!=clList_m.end();CP++ )
  {
    unsigned int x =  CP->clSize+1;        
    int y = Distribution_m[x]; //if not used we just show clasters on the image, usually y is used for deleting clusters with most usual size
      Ctraveller a ( CP->startx,CP->starty ,&ImageInClusterFormat_m );
      PaintClasterOnBitmap ( a,x<<8,CImage::NotVisited);    

  }    
}
//---------------------------------------------------------------------------
void CleanClass::PaintDistribution(int* img_,int width_,int height_,int color_)
{
  for ( unsigned int i =0;i<Distribution_m.size();i++ )
  {
    double x = i;
    double y = Distribution_m[i];
    if ( y )
    {
      int iks=int(log(x*50+1)*50);
      int ygrek=int(log(y*50)*50);
      if (iks>=width_) iks=width_-1;
      if (ygrek>=height_) ygrek=height_-1;
      if (iks<=0) iks=1;
      if (ygrek<=0) ygrek=1;
      img_[iks+width_*(height_-ygrek)]=color_;
      y = pow(x,-2.0549450549450549450549450549451);  
      iks=int(log(x*50+1)*50);
      ygrek=int(log(y*50)*50)+500;  
      if (iks>=width_) iks=width_-1;
      if (ygrek>=height_) ygrek=height_-1;   
      if (iks<=0) iks=1;
      if (ygrek<=0) ygrek=1;           
      img_[iks+width_*(height_-ygrek)]=255<<16;
    }     
  }  
  printf ( "Distribution painted\n");  
}
//---------------------------------------------------------------------------
void CleanClass::CleanPaintBackBW(int x1,int y1,int x2,int y2,int width_,int height_)
{
  double k = double((height_-y2)-(height_-y1))/double(x2-x1);
  double b = double((height_-y1))-k*double(x1);
  printf ( "Clean process BW 1 do k=%f b=%f\n",k,b);

  for ( int x = 0; x < Width_m; x++ )
    for ( int y = 0; y < Height_m; y ++ )
    {
      int sum=ImageInClusterFormat_m.IfMarked( x, y,CImage::NotDeleted );  
      img_m [x+Width_m*y] = sum*255; 
    }  
  
  for ( vector< clInfo >::iterator CP = clList_m.begin();CP!=clList_m.end();CP++ )
  {
    unsigned int x =  CP->clSize+1;        
    double X = log(x*50)*50;
    double y = Distribution_m[x];
    double Y = y?  log(y*50)*50:-10000;
    double delta2 = /*fabs*/(Y-k*X-b)/sqrt(1+k*k);//if abs than far from, if commented - than left from
 
    if (delta2>0)
    {
      Ctraveller a ( CP->startx,CP->starty ,&ImageInClusterFormat_m );
      PaintClasterOnBitmap ( a,0,CImage::NotVisited);    
    }
    else
    {
      Ctraveller a ( CP->startx,CP->starty ,&ImageInClusterFormat_m );
      PaintClasterOnBitmap ( a,255,CImage::NotVisited);    
    }
  }  
    
/*  for ( int x = 0; x < Width_m; x++ )
    for ( int y = 0; y < Height_m; y ++ )
    {
      int sum=ImageInClusterFormat_m.GetColor( x, y );  
      img_m [y+Height_m*x] = sum*255; 
    } */
}
//---------------------------------------------------------------------------
void CleanClass::CleanPaintBack(int* img_,int x1,int y1,int x2,int y2,int width_,int height_)
{
  double k = double((height_-y2)-(height_-y1))/double(x2-x1);
  double b = double((height_-y1))-k*double(x1);
  printf ( "Clean process 1 do k=%f b=%f\n",k,b);
  ImageInClusterFormat_m.SetOutput(img_);
  imgout_m = img_;

  for ( int x = 0; x < Width_m; x++ )
    for ( int y = 0; y < Height_m; y ++ )
    {
      int sum=ImageInClusterFormat_m.IfMarked( x, y,CImage::NotDeleted );  
      imgout_m [x+Width_m*y] = sum*255; 
    }  
  
  printf("CleanPaintBack cleanimg, clasters found %d\n",clList_m.size());  
  int FilteredCl_=0;
  //premark clusters for deletion
  for ( vector< clInfo >::iterator CP = clList_m.begin();CP!=clList_m.end();CP++ )
  {
    unsigned int x =  CP->clSize+1;        
    double X = log(x*50)*50;
    double y = Distribution_m[x];
    double Y = y?  log(y*50)*50:-10000;
    double delta2 = /*fabs*/(Y-k*X-b)/sqrt(1+k*k);//if abs than far from, if commented - than left from, in case of left from delta should be compared to 0
 
    if (delta2>=0)
    {
      Ctraveller a ( CP->startx,CP->starty ,&ImageInClusterFormat_m );
      MarkClaster ( a,CImage::Deleted);    
    }
  }
  
  for ( vector< clInfo >::iterator CP = clList_m.begin();CP!=clList_m.end();CP++ )
  {
    unsigned int x =  CP->clSize+1;        
    double X = log(x*50)*50;
    double y = Distribution_m[x];
    double Y = y?  log(y*50)*50:-10000;
    double delta2 = fabs(Y-k*X-b)/sqrt(1+k*k);//if abs than far from, if commented - than left from, in case of left from delta should be compared to 0
 
    if (delta2>=30)
    {
      Ctraveller a ( CP->startx,CP->starty ,&ImageInClusterFormat_m );
      //PaintClasterOnBitmap ( a,x*delta2*10000,CImage::NotVisited);
      //PaintClasterOnBitmap ( a,a.GetColorBitmap(),CImage::NotVisited);
      //CopyClasterOnBitmap ( a,CImage::NotVisited);    
      PaintGibbsMeasureOnBitmap( a,CImage::NotVisited); 
      //FilterClasterOnBitmap ( a,CImage::NotVisited);  
    }
    else
    {
      Ctraveller a ( CP->startx,CP->starty ,&ImageInClusterFormat_m );
      //FilterClasterOnBitmap ( a,CImage::NotVisited);    
      PaintGibbsMeasureOnBitmap( a,CImage::NotVisited); 
      FilteredCl_++;
    }
  }  
  printf("CleanPaintBack cleaning comlite, clasters filtered %d\n",FilteredCl_);  
    
/*  for ( int x = 0; x < Width_m; x++ )
    for ( int y = 0; y < Height_m; y ++ )
    {
      int sum=ImageInClusterFormat_m.GetColor( x, y );  
      img_m [y+Height_m*x] = sum*255; 
    } */
}
//---------------------------------------------------------------------------
void CleanClass::PaintBackNoClean(int* img_)//has meaning only if not evry point is part of some cluster
{
  for ( int x = 0; x < Width_m; x++ )
    for ( int y = 0; y < Height_m; y ++ )
    {
      int sum=ImageInClusterFormat_m.IfMarked( x, y,CImage::NotVisited ); 
      img_ [x+Width_m*y] = sum*255;
    }
}

void CleanClass::doProcess()
{
  ExtractAllClasters ( ImageInClusterFormat_m );
  printf("distribution computed\n");
}

void CleanClass::ExtractAllClasters ( CImage &Image )
{
  Distribution_m.resize(1,0);
  for ( int y = 0; y < Image.GetHeight(); y++ )
    for ( int x = 0; x < Image.GetWidth(); x++ )
    {
      if ( ( Image.ShouldExtract( x,y )) && ( Image.IfMarked( x,y,CImage::NotVisited )) )
      {                  
        Ctraveller a ( x,y ,&Image );
        unsigned int clSize_ =  MarkClaster ( a,CImage::Visited ); // each point has a marker - it shows if it is already treveled about.
        if (Distribution_m.size() < clSize_) 
        {
          Distribution_m.resize(clSize_+1,0);
        }
        Distribution_m[clSize_]+=1;
        clList_m.push_back(clInfo(x,y,clSize_));
      }
    }
  printf ( "Max size %d\n",Distribution_m.size());
}

